/* eslint-disable @typescript-eslint/no-explicit-any */
import  { useState, useRef, useEffect } from 'react';
import axios from 'axios';
import { 
  CloudUpload, 
  Pause, 
  Play, 
  Trash2, 
  Check, 
  AlertCircle,
  File,
  Clock,
  RefreshCw
} from 'lucide-react';

// 处理大文件切片的工具函数
const fileUtils = {
  // 计算文件的hash值（用于秒传判断）
  async calculateFileHash(file, onProgress) {
    return new Promise((resolve) => {
      const chunkSize = 2 * 1024 * 1024; // 2MB每块
      const chunks = Math.ceil(file.size / chunkSize);
      let currentChunk = 0;
      const spark = new (window.SparkMD5.ArrayBuffer || window.SparkMD5)();
      const fileReader = new FileReader();

      const loadNextChunk = () => {
        const start = currentChunk * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        fileReader.readAsArrayBuffer(file.slice(start, end));
      };

      fileReader.onload = (e) => {
        spark.append(e.target.result);
        currentChunk++;
        
        // 计算并回调进度
        const progress = Math.floor((currentChunk / chunks) * 100);
        onProgress(progress);
        
        if (currentChunk < chunks) {
          loadNextChunk();
        } else {
          const hash = spark.end();
          resolve(hash);
        }
      };

      loadNextChunk();
    });
  },

  // 分割文件为切片
  sliceFile(file, chunkSize = 2 * 1024 * 1024) {
    const chunks = [];
    let current = 0;
    
    while (current < file.size) {
      chunks.push({
        file: file.slice(current, current + chunkSize),
        index: chunks.length
      });
      current += chunkSize;
    }
    
    return chunks;
  }
};

// 上传管理器 - 处理上传逻辑
const UploadManager = {
  // 检查文件是否已上传（秒传检查）
  async checkFileExists(hash) {
    try {
      const response = await axios.post('/api/check-file', { hash });
      return response.data.exists;
    } catch (error) {
      console.error('检查文件存在性失败:', error);
      return false;
    }
  },

  // 初始化上传
  async initUpload(file, hash) {
    try {
      const response = await axios.post('/api/init-upload', {
        fileName: file.name,
        fileSize: file.size,
        fileHash: hash,
        mimeType: file.type
      });
      return response.data.uploadId;
    } catch (error) {
      console.error('初始化上传失败:', error);
      throw error;
    }
  },

  // 上传单个切片
  async uploadChunk(uploadId, fileHash, chunk, chunkIndex, totalChunks) {
    const formData = new FormData();
    formData.append('uploadId', uploadId);
    formData.append('fileHash', fileHash);
    formData.append('chunkIndex', chunkIndex);
    formData.append('totalChunks', totalChunks);
    formData.append('chunk', chunk.file);

    try {
      const response = await axios.post('/api/upload-chunk', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
        onUploadProgress: (e) => {
          // 可以在这里处理单个切片的上传进度
        }
      });
      return response.data;
    } catch (error) {
      console.error(`上传切片 ${chunkIndex} 失败:`, error);
      throw error;
    }
  },

  // 合并切片
  async mergeChunks(uploadId, fileHash, fileName, totalChunks) {
    try {
      const response = await axios.post('/api/merge-chunks', {
        uploadId,
        fileHash,
        fileName,
        totalChunks
      });
      return response.data;
    } catch (error) {
      console.error('合并切片失败:', error);
      throw error;
    }
  }
};

const FileUploader = () => {
  const [files, setFiles] = useState([]);
  const [dragging, setDragging] = useState(false);
  const fileInputRef = useRef(null);
  const [uploadingFiles, setUploadingFiles] = useState([]);
  const [completedFiles, setCompletedFiles] = useState([]);
  const concurrentUploads = 3; // 并发上传数量

  // 从本地存储加载未完成的上传
  useEffect(() => {
    const loadPendingUploads = () => {
      const savedUploads = localStorage.getItem('pendingUploads');
      if (savedUploads) {
        setUploadingFiles(JSON.parse(savedUploads));
      }

      const savedCompleted = localStorage.getItem('completedUploads');
      if (savedCompleted) {
        setCompletedFiles(JSON.parse(savedCompleted));
      }
    };

    loadPendingUploads();
  }, []);

  // 保存上传状态到本地存储
  useEffect(() => {
    localStorage.setItem('pendingUploads', JSON.stringify(
      uploadingFiles.filter(file => file.status !== 'completed' && file.status !== 'error')
    ));
    localStorage.setItem('completedUploads', JSON.stringify(completedFiles));
  }, [uploadingFiles, completedFiles]);

  // 处理文件选择
  const handleFileSelect = (selectedFiles) => {
    const newFiles = Array.from(selectedFiles).map(file => ({
      id: Date.now() + Math.random().toString(36).substr(2, 9),
      name: file.name,
      size: file.size,
      type: file.type,
      file,
      progress: 0,
      status: 'pending', // pending, hashing, uploading, paused, completed, error
      hash: null,
      uploadId: null,
      chunks: [],
      uploadedChunks: [],
      error: null
    }));

    setFiles(prev => [...prev, ...newFiles]);
    
    // 自动开始处理文件
    newFiles.forEach(file => processFile(file));
  };

  // 处理拖放
  const handleDragOver = (e) => {
    e.preventDefault();
    setDragging(true);
  };

  const handleDragLeave = () => {
    setDragging(false);
  };

  const handleDrop = (e) => {
    e.preventDefault();
    setDragging(false);
    if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
      handleFileSelect(e.dataTransfer.files);
    }
  };

  // 触发文件选择对话框
  const triggerFileSelect = () => {
    fileInputRef.current.click();
  };

  // 处理文件上传流程
  const processFile = async (file) => {
    // 将文件添加到上传列表
    setUploadingFiles(prev => [...prev, { ...file }]);
    
    try {
      // 1. 计算文件hash
      updateFileStatus(file.id, 'hashing', 0);
      
      const hash = await fileUtils.calculateFileHash(file.file, (progress) => {
        updateFileProgress(file.id, progress);
      });
      
      // 2. 检查文件是否已上传（秒传）
      const fileExists = await UploadManager.checkFileExists(hash);
      
      if (fileExists) {
        // 秒传：直接标记为已完成
        updateFileStatus(file.id, 'completed', 100);
        updateFileMetadata(file.id, { hash });
        
        // 移至已完成列表
        moveToCompleted(file.id);
        return;
      }
      
      // 3. 初始化上传
      const uploadId = await UploadManager.initUpload(file.file, hash);
      const chunks = fileUtils.sliceFile(file.file);
      
      updateFileMetadata(file.id, { 
        hash, 
        uploadId, 
        chunks,
        totalChunks: chunks.length 
      });
      
      // 4. 开始上传切片
      updateFileStatus(file.id, 'uploading', 0);
      startChunkUploads(file.id);
      
    } catch (error) {
      console.error('文件处理失败:', error);
      updateFileStatus(file.id, 'error', file.progress, error.message || '上传失败');
    }
  };

  // 开始上传切片
  const startChunkUploads = (fileId) => {
    const file = uploadingFiles.find(f => f.id === fileId);
    if (!file || file.status !== 'uploading') return;
    
    // 获取尚未上传的切片
    const chunksToUpload = file.chunks
      .filter((_, index) => !file.uploadedChunks.includes(index))
      .slice(0, concurrentUploads);
    
    if (chunksToUpload.length === 0) {
      // 所有切片已上传，开始合并
      mergeFileChunks(fileId);
      return;
    }
    
    // 上传选中的切片
    chunksToUpload.forEach(chunk => {
      uploadChunk(fileId, chunk.index);
    });
  };

  // 上传单个切片
  const uploadChunk = async (fileId, chunkIndex) => {
    const file = uploadingFiles.find(f => f.id === fileId);
    if (!file || file.status !== 'uploading') return;
    
    try {
      await UploadManager.uploadChunk(
        file.uploadId,
        file.hash,
        file.chunks[chunkIndex],
        chunkIndex,
        file.totalChunks
      );
      
      // 标记切片为已上传
      const updatedUploadedChunks = [...file.uploadedChunks, chunkIndex];
      updateFileMetadata(fileId, { uploadedChunks: updatedUploadedChunks });
      
      // 更新整体进度
      const progress = Math.floor((updatedUploadedChunks.length / file.totalChunks) * 100);
      updateFileProgress(fileId, progress);
      
      // 继续上传其他切片
      startChunkUploads(fileId);
      
    } catch (error) {
      console.error(`切片 ${chunkIndex} 上传失败`, error);
      
      // 如果是暂停状态，不处理错误
      const currentFile = uploadingFiles.find(f => f.id === fileId);
      if (currentFile?.status === 'uploading') {
        updateFileStatus(fileId, 'error', file.progress, '网络错误，点击继续重试');
      }
    }
  };

  // 合并文件切片
  const mergeFileChunks = async (fileId) => {
    const file = uploadingFiles.find(f => f.id === fileId);
    if (!file) return;
    
    try {
      await UploadManager.mergeChunks(
        file.uploadId,
        file.hash,
        file.name,
        file.totalChunks
      );
      
      // 标记为已完成
      updateFileStatus(fileId, 'completed', 100);
      moveToCompleted(fileId);
      
    } catch (error) {
      console.error('合并切片失败', error);
      updateFileStatus(fileId, 'error', 100, '合并失败，点击重试');
    }
  };

  // 暂停上传
  const pauseUpload = (fileId) => {
    updateFileStatus(fileId, 'paused');
  };

  // 继续上传
  const resumeUpload = (fileId) => {
    const file = uploadingFiles.find(f => f.id === fileId);
    if (!file) return;
    
    updateFileStatus(fileId, 'uploading', file.progress);
    
    // 如果还在计算hash，重新开始计算
    if (file.status === 'hashing') {
      processFile(file);
    } else {
      // 继续上传切片
      startChunkUploads(fileId);
    }
  };

  // 取消上传
  const cancelUpload = (fileId) => {
    setUploadingFiles(prev => prev.filter(file => file.id !== fileId));
  };

  // 移除已完成的文件
  const removeCompletedFile = (fileId) => {
    setCompletedFiles(prev => prev.filter(file => file.id !== fileId));
  };

  // 更新文件进度
  const updateFileProgress = (fileId, progress) => {
    setUploadingFiles((prev:any) => 
      prev.map( (file:any)=>
        file.id === fileId ? { ...file, progress } : file
      )
    );
  };

  // 更新文件状态
  const updateFileStatus = (fileId, status, progress = null, error = null) => {
    setUploadingFiles((prev:any) => 
      prev.map( (file:any)=>{
        if (file.id === fileId) {
          return { 
            ...file, 
            status,
            progress: progress !== null ? progress : file.progress,
            error: error || file.error
          };
        }
        return file;
      })
    );
  };

  // 更新文件元数据
  const updateFileMetadata = (fileId, metadata) => {
    setUploadingFiles((prev:any) => 
      prev.map( (file:any)=> 
        file.id === fileId ? { ...file, ...metadata } : file
      )
    );
  };

  // 将文件移至已完成列表
  const moveToCompleted = (fileId) => {
    const file = uploadingFiles.find(f => f.id === fileId);
    if (file) {
      setCompletedFiles(prev => [...prev, file]);
      setUploadingFiles(prev => prev.filter(f => f.id !== fileId));
    }
  };

  // 格式化文件大小
  const formatFileSize = (bytes) => {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };

  // 渲染上传状态图标
  const renderStatusIcon = (status) => {
    switch (status) {
      case 'hashing':
        return <RefreshCw className="w-4 h-4 text-blue-500 animate-spin" />;
      case 'uploading':
        return <CloudUpload className="w-4 h-4 text-blue-500 animate-pulse" />;
      case 'paused':
        return <Clock className="w-4 h-4 text-amber-500" />;
      case 'completed':
        return <Check className="w-4 h-4 text-green-500" />;
      case 'error':
        return <AlertCircle className="w-4 h-4 text-red-500" />;
      default:
        return <File className="w-4 h-4 text-gray-500" />;
    }
  };

  // 渲染控制按钮.

  const renderControlButtons = (file) => {
    switch (file.status) {
      case 'uploading':
        return (
          <button 
            onClick={() => pauseUpload(file.id)}
            className="p-1.5 text-amber-500 hover:text-amber-700 hover:bg-amber-50 rounded-full transition-colors"
            title="暂停"
          >
            <Pause className="w-4 h-4" />
          </button>
        );
      case 'paused':
      case 'error':
        return (
          <button 
            onClick={() => resumeUpload(file.id)}
            className="p-1.5 text-green-500 hover:text-green-700 hover:bg-green-50 rounded-full transition-colors"
            title="继续"
          >
            <Play className="w-4 h-4" />
          </button>
        );8``
      case 'completed':
        return null;
      default:
        return (
          <button 
            onClick={() => cancelUpload(file.id)}
            className="p-1.5 text-red-500 hover:text-red-700 hover:bg-red-50 rounded-full transition-colors"
            title="取消"
          >
            <Trash2 className="w-4 h-4" />
          </button>
        );
    }
  };

  return (
    <div className="max-w-4xl mx-auto p-4 bg-white rounded-xl shadow-lg">
      <h2 className="text-2xl font-bold text-gray-800 mb-6">高级文件上传器</h2>
      
      {/* 上传区域 */}
      <div
        className={`
          border-2 border-dashed rounded-lg p-10 text-center mb-8 cursor-pointer transition-all
          ${dragging 
            ? 'border-blue-500 bg-blue-50' 
            : 'border-gray-300 hover:border-blue-400 hover:bg-blue-50'
          }
        `}
        onClick={triggerFileSelect}
        onDragOver={handleDragOver}
        onDragLeave={handleDragLeave}
        onDrop={handleDrop}
      >
        <input
          type="file"
          ref={fileInputRef}
          multiple
          className="hidden"
          onChange={(e) => handleFileSelect(e.target.files)}
        />
        
        <CloudUpload className="w-12 h-12 mx-auto text-blue-500 mb-4" />
        <h3 className="text-lg font-medium text-gray-700 mb-2">拖放文件到此处或点击上传</h3>
        <p className="text-gray-500 text-sm">
          支持大文件上传、断点续传和秒传功能
        </p>
      </div>
      
      {/* 上传中文件列表 */}
      {uploadingFiles.length > 0 && (
        <div className="mb-8">
          <h3 className="text-lg font-semibold text-gray-700 mb-3">上传中</h3>
          <div className="space-y-4">
            {uploadingFiles.map(file => (
              <div key={file.id} className="p-4 bg-gray-50 rounded-lg shadow-sm">
                <div className="flex justify-between items-start mb-2">
                  <div className="flex items-center">
                    {renderStatusIcon(file.status)}
                    <div className="ml-3">
                      <div className="font-medium text-gray-800 truncate max-w-md">{file.name}</div>
                      <div className="text-sm text-gray-500">
                        {formatFileSize(file.size)} · {file.progress}%
                      </div>
                    </div>
                  </div>
                  <div className="flex space-x-1">
                    {renderControlButtons(file)}
                    {(file.status === 'paused' || file.status === 'error') && (
                      <button 
                        onClick={() => cancelUpload(file.id)}
                        className="p-1.5 text-red-500 hover:text-red-700 hover:bg-red-50 rounded-full transition-colors"
                        title="取消"
                      >
                        <Trash2 className="w-4 h-4" />
                      </button>
                    )}
                  </div>
                </div>
                
                {/* 进度条 */}
                <div className="w-full bg-gray-200 rounded-full h-2.5 mt-2 overflow-hidden">
                  <div
                    className={`
                      h-full rounded-full transition-all duration-300
                      ${file.status === 'error' 
                        ? 'bg-red-500' 
                        : file.status === 'completed'
                          ? 'bg-green-500'
                          : 'bg-blue-500'
                      }
                    `}
                    style={{ width: `${file.progress}%` }}
                  />
                </div>
                
                {/* 错误信息 */}
                {file.error && (
                  <p className="text-sm text-red-500 mt-2 flex items-center">
                    <AlertCircle className="w-3.5 h-3.5 mr-1" />
                    {file.error}
                  </p>
                )}
              </div>
            ))}
          </div>
        </div>
      )}
      
      {/* 已完成文件列表 */}
      {completedFiles.length > 0 && (
        <div>
          <h3 className="text-lg font-semibold text-gray-700 mb-3">已完成</h3>
          <div className="space-y-3">
            {completedFiles.map(file => (
              <div key={file.id} className="p-3 bg-gray-50 rounded-lg shadow-sm flex justify-between items-center">
                <div className="flex items-center">
                  <Check className="w-4 h-4 text-green-500 mr-2" />
                  <span className="text-gray-700 truncate max-w-md">{file.name}</span>
                  <span className="text-sm text-gray-500 ml-2">{formatFileSize(file.size)}</span>
                </div>
                <button 
                  onClick={() => removeCompletedFile(file.id)}
                  className="p-1 text-gray-400 hover:text-red-500 transition-colors"
                  title="删除"
                >
                  <Trash2 className="w-4 h-4" />
                </button>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
};

export default FileUploader;
